package ru.pomarshrutu.server;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import ru.pomarshrutu.server.model.Point;
import ru.pomarshrutu.server.model.Recording;

public class SimpleUploadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	private PersistenceManager persistenceManager;

	private Query pointQuery;

	private Query recordingQuery;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		persistenceManager = PersistenceFacade.getInstance().getPersistenceManager();
		
		pointQuery = persistenceManager.newQuery(Point.class);
		pointQuery.setFilter("coordinates == coordinatesParam");
		pointQuery.declareParameters("String coordinatesParam");
		
		recordingQuery = persistenceManager.newQuery(Recording.class);
		recordingQuery.setFilter("id == idParam");
		recordingQuery.declareParameters("Long idParam");
	}

	@SuppressWarnings("unchecked")
	public void service(HttpServletRequest req, HttpServletResponse res)
	throws ServletException, IOException {
		String action = req.getParameter("action");
		if("addPoint".equals(action)) {
			String coordinates = req.getParameter("coordinates");
			if(coordinates == null) {
				res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				return;
			}
			
			try {
				ServletFileUpload upload = new ServletFileUpload();
	
				FileItemIterator iterator = upload.getItemIterator(req);
				while (iterator.hasNext()) {
					FileItemStream item = iterator.next();
					InputStream stream = item.openStream();
	
					if (!item.isFormField()) {
						byte[] file = readToByteArray(stream);
						
						//we do the below things to persist files larger 1Mb
						Recording recording = new Recording(file, persistenceManager);	//recording is persisted after this call
						persistenceManager.makePersistent(new Point(coordinates, recording.getId()));
					}
				}
			} catch (Exception ex) {
				throw new ServletException(ex);
			}
		}
		else if("removePoint".equals(action)) {
			String coordinates = req.getParameter("coordinates");
			if(coordinates == null) {
				res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				return;
			}
			
			List<Point> points = (List<Point>)pointQuery.execute(coordinates);
			for(Point point : points) {
				List<Recording> recordings = (List<Recording>)recordingQuery.execute(point.getRecordingId());
				for(Recording recording : recordings) { //there is only one in fact
					persistenceManager.deletePersistent(recording);
				}
				
				persistenceManager.deletePersistent(point);
			}
		}
	}
	
	private byte[] readToByteArray(InputStream inputStream) throws IOException {
		int bufsize = 8192;
		byte[] buf = new byte[bufsize];
		int read = 0;
		byte[] ret = null;
		
		while((read = inputStream.read(buf)) != -1) {
			if(ret != null) {
				byte[] newRet = new byte[ret.length + read];
				System.arraycopy(ret, 0, newRet, 0, ret.length);
				System.arraycopy(buf, 0, newRet, ret.length, read);
				ret = newRet;
			}
			else {
				ret = new byte[read];
				System.arraycopy(buf, 0, ret, 0, read);
			}
		}
		
		return ret;
	}
}